package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"go.uber.org/zap"

	_ "dcarpai-guider/docs" // Swagger 文档
	"dcarpai-guider/internal/controllers"
	"dcarpai-guider/internal/middleware"
	"dcarpai-guider/internal/services"
	"dcarpai-guider/internal/utils"
)

// @title DCarpai Guider API
// @version 1.0
// @description 懂车拍管理平台 API 文档
// @host localhost:8080
// @BasePath /api/v1
// @schemes http
func main() {
	// 创建日志目录
	if err := os.MkdirAll("logs", 0755); err != nil {
		log.Printf("警告：无法创建日志目录: %v", err)
	}

	// 初始化自定义日志服务
	var loggerService *services.LoggerService
	if logService, err := services.NewLoggerService(services.LoggerConfig{
		LogDir:     "logs",
		Level:      "info",
		Format:     "json",
		MaxSize:    100,  // 100MB
		MaxBackups: 5,    // 保留5个备份
		MaxAge:     30,   // 保留30天
		Compress:   true, // 压缩旧文件
		Rotation:   true, // 启用轮转
	}); err != nil {
		log.Printf("警告：无法初始化日志服务: %v", err)
	} else {
		loggerService = logService
		defer loggerService.Close()
	}

	// 初始化zap日志（保持现有兼容性）
	logger, err := initLogger()
	if err != nil {
		log.Fatalf("初始化日志失败: %v", err)
	}
	defer logger.Sync()

	if loggerService != nil {
		loggerService.LogOperation("应用启动", "系统", "应用", map[string]interface{}{
			"version": "1.0.0",
			"env":     gin.Mode(),
		})
	}

	logger.Info("正在启动 DCarpai Guider 服务...")

	// 初始化文件管理器
	fileManager := utils.NewFileManager()

	// 初始化Consul客户端（可选）
	var consulClient *utils.ConsulClient
	consulClient, err = utils.NewConsulClient("localhost:8500")
	if err != nil {
		logger.Warn("无法连接到Consul，将在无服务发现的情况下运行", zap.Error(err))
		if loggerService != nil {
			loggerService.LogOperation("Consul连接失败", "系统", "服务发现", map[string]interface{}{
				"error":   err.Error(),
				"address": "localhost:8500",
			})
		}
		consulClient = nil
	}

	// 启动文件监控
	if err := startFileWatcher(logger, fileManager); err != nil {
		logger.Error("启动文件监控失败", zap.Error(err))
	}

	// 设置Gin模式
	gin.SetMode(gin.ReleaseMode)

	// 创建Gin路由器
	router := gin.New()

	// 添加中间件
	router.Use(gin.Logger())
	router.Use(gin.Recovery())

	// CORS中间件
	router.Use(func(c *gin.Context) {
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusOK)
			return
		}

		c.Next()
	})

	// 获取端口配置
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	portInt := 8080
	if p, err := strconv.Atoi(port); err == nil {
		portInt = p
	}

	// 设置路由
	setupRoutes(router, logger, fileManager, consulClient, loggerService)

	// 注册服务到Consul（如果可用）
	if consulClient != nil {
		serviceID := "dcarpai-guider-001"
		if err := consulClient.RegisterService(
			serviceID,
			"dcarpai-guider",
			"localhost",
			portInt,
			[]string{"web", "management", "api"},
		); err != nil {
			logger.Error("注册服务到Consul失败", zap.Error(err))
		} else {
			logger.Info("已注册服务到Consul", zap.String("service_id", serviceID))
		}

		// 确保在程序退出时注销服务
		defer func() {
			if err := consulClient.DeregisterService(serviceID); err != nil {
				logger.Error("注销服务失败", zap.Error(err))
			}
		}()
	}

	addr := ":" + port

	// 创建HTTP服务器
	srv := &http.Server{
		Addr:    addr,
		Handler: router,
	}

	// 在goroutine中启动服务器
	go func() {
		logger.Info("HTTP服务器正在启动", zap.String("address", addr))
		if loggerService != nil {
			loggerService.LogOperation("HTTP服务器启动", "系统", "网络", map[string]interface{}{
				"port": port,
			})
		}
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.Fatal("启动HTTP服务器失败", zap.Error(err))
		}
	}()

	// 等待中断信号以优雅地关闭服务器
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	logger.Info("正在关闭服务器...")

	// 设置5秒超时上下文进行优雅关闭
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		logger.Error("服务器强制关闭", zap.Error(err))
	}

	logger.Info("服务器已退出")
}

// initLogger 初始化日志
func initLogger() (*zap.Logger, error) {
	// 创建日志目录
	if err := os.MkdirAll("logs", 0755); err != nil {
		return nil, fmt.Errorf("创建日志目录失败: %w", err)
	}

	// 基础配置
	config := zap.NewProductionConfig()
	config.OutputPaths = []string{
		"stdout",
		fmt.Sprintf("logs/dcarpai-guider-%s.log", time.Now().Format("2006010215")),
	}
	config.ErrorOutputPaths = []string{
		"stderr",
		fmt.Sprintf("logs/dcarpai-guider-%s.log", time.Now().Format("2006010215")),
	}

	return config.Build()
}

// setupRoutes 设置路由
func setupRoutes(router *gin.Engine, logger *zap.Logger, fileManager *utils.FileManager, consulClient *utils.ConsulClient, loggerService *services.LoggerService) {
	// 初始化服务层
	userService := services.NewUserService(fileManager, logger)
	toolService := services.NewToolService(fileManager, consulClient, logger)
	configService := services.NewConfigService(fileManager, logger)

	// 初始化控制器
	authController := controllers.NewAuthController(userService, logger)
	toolController := controllers.NewToolController(toolService, logger)
	configController := controllers.NewConfigController(configService, logger)
	userController := controllers.NewUserController(userService, logger, loggerService)
	healthController := controllers.NewHealthController(logger, consulClient)

	// API v1 组
	v1 := router.Group("/api/v1")

	// Swagger文档路由
	router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	// 健康检查端点
	router.GET("/health", healthController.BasicHealth)
	router.GET("/health/ready", healthController.GetReadiness)
	router.GET("/health/live", healthController.GetLiveness)

	// 基础信息端点
	v1.GET("/info", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"name":    "DCarpai Guider",
			"version": "1.0.0",
			"author":  "DCarpai Team",
		})
	})

	// 认证相关路由（不需要认证）
	auth := v1.Group("/auth")
	{
		auth.POST("/login", authController.Login)
		auth.POST("/logout", middleware.AuthMiddleware(), authController.Logout)
	}

	// 需要认证的路由组
	authenticated := v1.Group("/")
	authenticated.Use(middleware.AuthMiddleware())
	{
		// 用户相关路由
		authenticated.GET("/users/profile", authController.GetProfile)

		// 健康检查相关路由
		authenticated.GET("/health/detailed", healthController.DetailedHealth)

		// 工具相关路由
		authenticated.GET("/tools", toolController.GetAllTools)
		authenticated.GET("/tools/active", toolController.GetActiveTools)
		authenticated.GET("/tools/:id", toolController.GetTool)
		authenticated.POST("/tools", toolController.CreateTool)
		authenticated.PUT("/tools/:id", toolController.UpdateTool)
		authenticated.DELETE("/tools/:id", toolController.DeleteTool)
		authenticated.GET("/tools/:id/status", toolController.GetToolStatus)

		// 配置相关路由
		authenticated.GET("/configs", configController.GetAllConfigs)
		authenticated.GET("/configs/:name", configController.GetConfig)
		authenticated.POST("/configs", configController.CreateConfig)
		authenticated.PUT("/configs/:name", configController.UpdateConfig)
		authenticated.DELETE("/configs/:name", configController.DeleteConfig)
		authenticated.POST("/configs/:name/backup", configController.BackupConfig)

		// Consul健康检查
		if consulClient != nil {
			authenticated.GET("/consul/health", func(c *gin.Context) {
				healths, err := consulClient.GetServiceHealths()
				if err != nil {
					logger.Error("获取服务健康状态失败", zap.Error(err))
					c.JSON(http.StatusInternalServerError, gin.H{
						"code":    500,
						"message": "获取服务健康状态失败",
						"error":   err.Error(),
					})
					return
				}

				c.JSON(http.StatusOK, gin.H{
					"code": 200,
					"data": healths,
				})
			})
		}
	}

	// 需要管理员权限的路由组
	admin := v1.Group("/admin")
	admin.Use(middleware.AuthMiddleware())
	admin.Use(middleware.AdminMiddleware())
	{
		admin.GET("/users", userController.GetAllUsers)
		admin.POST("/users", userController.CreateUser)
		admin.GET("/users/stats", userController.GetUserStats)
	}
} // startFileWatcher 启动文件监控
func startFileWatcher(logger *zap.Logger, fileManager *utils.FileManager) error {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return fmt.Errorf("创建文件监控器失败: %w", err)
	}

	// 在goroutine中处理事件
	go func() {
		defer watcher.Close()
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				logger.Info("文件变更",
					zap.String("file", event.Name),
					zap.String("op", event.Op.String()),
				)

			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				logger.Error("文件监控错误", zap.Error(err))
			}
		}
	}()

	// 监控数据目录
	dataDir := "./data"
	if err := watcher.Add(dataDir); err != nil {
		return fmt.Errorf("添加监控目录失败: %w", err)
	}

	// 监控配置目录
	configDir := "./data/configs"
	if err := watcher.Add(configDir); err != nil {
		return fmt.Errorf("添加配置监控目录失败: %w", err)
	}

	logger.Info("文件监控已启动",
		zap.Strings("watched_dirs", []string{dataDir, configDir}),
	)

	return nil
}
